home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 10 / FreelogHS10.iso / Buzz / Buzz_Advanced_Pack.exe / {app} / Dev / MidiRecExample.txt < prev    next >
Text File  |  2001-08-27  |  4KB  |  255 lines

  1. // allocated track:
  2. // 1. same LastNote if note not in pattern
  3. // 2. first free with no note in pattern
  4. // 3. first free
  5. // 4. track with oldest high note (C6+)
  6. // 5. track with oldest mid note (C3+)
  7. // 6. track with oldest note
  8.  
  9. int mi::AllocateTrack(CSequence *pseq, int note)
  10. {
  11.     
  12.     for (int c = 0; c < numTracks; c++)
  13.     {
  14.         if (Tracks[c].LastNote == note)
  15.         {
  16.             if (pseq != NULL)
  17.             {
  18.                 byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
  19.                 if (*pdata == NOTE_NO)
  20.                     return c;
  21.                 
  22.             }
  23.             
  24.         }
  25.     }
  26.  
  27.     int best = -1;
  28.  
  29.  
  30.     for (c = 0; c < numTracks; c++)
  31.     {
  32.         if (Tracks[c].Voices[Tracks[c].FreeVoice^1].State == CVoice::inactive)
  33.         {
  34.             if (pseq != NULL)
  35.             {
  36.                 byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
  37.                 if (*pdata == NOTE_NO)
  38.                     return c;
  39.                 
  40.             }
  41.  
  42.             if (best == -1)
  43.                 best = c;
  44.         }
  45.     }
  46.  
  47.     if (best != -1)
  48.         return best;
  49.  
  50.     // if we got here it means all voices are active
  51.     int oldt = -1;
  52.     
  53.     // check high
  54.     for (c = 0; c < numTracks; c++)
  55.     {
  56.         if (Tracks[c].LastNote >= ((6 << 4) + 1))        // >= C6
  57.         {
  58.             int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
  59.             if (at > oldt)
  60.             {
  61.                 oldt = at;
  62.                 best = c;
  63.             }
  64.         }
  65.         
  66.     }
  67.  
  68.     if (best != -1)
  69.         return best;
  70.  
  71.     // check mid
  72.     for (c = 0; c < numTracks; c++)
  73.     {
  74.         if (Tracks[c].LastNote >= ((3 << 4) + 1))        // >= C3
  75.         {
  76.             int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
  77.             if (at > oldt)
  78.             {
  79.                 oldt = at;
  80.                 best = c;
  81.             }
  82.         }
  83.         
  84.     }
  85.     
  86.     if (best != -1)
  87.         return best;
  88.  
  89.     // check low
  90.     for (c = 0; c < numTracks; c++)
  91.     {
  92.         int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
  93.         if (at > oldt)
  94.         {
  95.             oldt = at;
  96.             best = c;
  97.         }
  98.     }
  99.         
  100.  
  101.     assert(best != -1);
  102.  
  103.     return best;
  104.  
  105. }
  106.  
  107. void miex::MidiControlChange(int const ctrl, int const channel, int const value)
  108. {
  109.     // TODO: check channel
  110.  
  111.     if (ctrl != 64)    // 64 = sustain pedal
  112.         return;
  113.  
  114.  
  115.     if (value < 64)
  116.     {
  117.         CSequence *pseq;
  118.  
  119.         int stateflags = pmi->pCB->GetStateFlags();
  120.         
  121.         if (stateflags & SF_PLAYING && stateflags & SF_RECORDING)
  122.             pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine);
  123.         else 
  124.             pseq = NULL;
  125.  
  126.         int notedelay = pmi->pMasterInfo->PosInTick * 24 / pmi->pMasterInfo->SamplesPerTick;
  127.         
  128.         pmi->SustainPedal = false;
  129.         for (int c = 0; c < pmi->numTracks; c++)
  130.         {
  131.             if (pmi->Tracks[c].Note != NOTE_NO && pmi->Tracks[c].Sustained)
  132.             {
  133.                 pmi->Tracks[c].Sustained = false;
  134.                 pmi->MidiNoteOff(c, pseq, notedelay);
  135.             }
  136.         }
  137.     }
  138.     else
  139.     {
  140.         pmi->SustainPedal = true;
  141.     }
  142.  
  143.  
  144.  
  145. }
  146.  
  147.  
  148. void mi::MidiNoteOff(int c, CSequence *pseq, int notedelay)
  149. {
  150.     Tracks[c].NoteOff();
  151.  
  152.     if (pseq != NULL)
  153.     {
  154.         byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
  155.  
  156.         if (notedelay > 0)
  157.         {
  158.             if (pdata[0] != NOTE_NO)
  159.             {
  160.                 if (pdata[2] == 0x0d)
  161.                 {
  162.                     int ondelay = pdata[3] >> 1;
  163.                     pdata[2] = 0x0b;
  164.                     pdata[3] = (ondelay << 4) | (notedelay >> 1);
  165.                 }
  166.                 else
  167.                 {
  168.                     // ondelay = 0
  169.                     pdata[2] = 0x0b;
  170.                     pdata[3] = (notedelay >> 1);
  171.                 }
  172.             }                        
  173.             else
  174.             {
  175.                 pdata[0] = NOTE_OFF;
  176.                 pdata[2] = 0x0d;
  177.                 pdata[3] = (byte)notedelay;
  178.             }
  179.         }
  180.         else
  181.         {
  182.             pdata[0] = NOTE_OFF;
  183.         }
  184.  
  185.  
  186.     }
  187.  
  188. }
  189.  
  190.  
  191. void mi::MidiNote(int const channel, int const value, int const velocity)
  192. {
  193.     // TODO: check channel
  194.  
  195.     if (value / 12 > 9)
  196.          return;    
  197.  
  198.     byte n = (((value / 12)-1) << 4) | ((value % 12) + 1);
  199.  
  200.     CSequence *pseq;
  201.  
  202.     int stateflags = pCB->GetStateFlags();
  203.     
  204.     if (stateflags & SF_PLAYING && stateflags & SF_RECORDING)
  205.         pseq = pCB->GetPlayingSequence(ThisMachine);
  206.     else 
  207.         pseq = NULL;
  208.  
  209.  
  210.     int notedelay = pMasterInfo->PosInTick * 24 / pMasterInfo->SamplesPerTick;
  211.  
  212.     if (velocity > 0)
  213.     {
  214.         int c = AllocateTrack(pseq, n);
  215.  
  216.         Tracks[c].Note = n;
  217.         Tracks[c].Velocity = velocity;
  218.         Tracks[c].NoteOn();
  219.  
  220.         if (pseq != NULL)
  221.         {
  222.             byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
  223.             pdata[0] = n;
  224.             pdata[1] = velocity;
  225.             
  226.             if (notedelay > 0)
  227.             {
  228.                 pdata[2] = 0x0d;
  229.                 pdata[3] = (byte)notedelay;
  230.             }
  231.         }
  232.     
  233.  
  234.     }
  235.     else
  236.     {
  237.         for (int c = 0; c < numTracks; c++)
  238.         {
  239.             if (Tracks[c].Note == n)
  240.             {
  241.                 if (SustainPedal)
  242.                     Tracks[c].Sustained = true;
  243.                 else
  244.                     MidiNoteOff(c, pseq, notedelay);
  245.  
  246.                 break;
  247.             }
  248.  
  249.             
  250.         }
  251.     }
  252.  
  253.  
  254. }
  255.